package raspberry_pi_app;

import io.socket.SocketIO;
import io.socket.IOCallback;
import io.socket.IOAcknowledge;
import io.socket.SocketIOException;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import org.apache.http.NameValuePair;
import org.apache.http.cookie.Cookie;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import bradz.media_server.raspberry_pi_app.R;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.webkit.CookieSyncManager;
import android.widget.TextView;

public class ClassNetworkHelper {

	ClassHttpHelper helper;
	private Context context;
	//private boolean pass_class;
	private Class<?> next_activity;
	//private String post_controller;
	private boolean applying;
	private ClassUberLogger logger;
	private SocketIO socket;
	//private ApplicationGlobalVars globals;
	
	ClassNetworkHelper(Context context, String base_url, ApplicationGlobalVars globals){
		this.context = context;
		CookieSyncManager.createInstance(context);
		helper = new ClassHttpHelper(base_url,globals);
		applying = false;
		logger = new ClassUberLogger("ClassNetworkHelper");
	}
	
	ClassNetworkHelper(Context context, ApplicationGlobalVars globals){
		this.context = context;
		CookieSyncManager.createInstance(context);
		helper = new ClassHttpHelper(context.getString(R.string.network_address),globals);
		applying = false;
		logger = new ClassUberLogger("ClassNetworkHelper");
	}
	
	public boolean applying(){
		return applying;
	}
	
	public void log_out_network(Handler handler){
		log_out_network_task login = new log_out_network_task();
		login.handler = handler;
		login.execute();
		logger.info("Logging out of network");
	}
	
	public void log_into_network(Class<?> next_activity,List<NameValuePair> pairs, boolean test_login){
		//pass_class = true;
		this.next_activity = next_activity;
		log_into_network_task login = new log_into_network_task(test_login,new ArrayList<NameValuePair>(pairs));
		logger.info("Logging into network");
		
		login.execute();
	
		logger.info("Cookie Store Size: " + helper.get_client().get_cookies().getCookies().size());
	}
	
	/*public void emit_socket(List<NameValuePair> pairs, String routing_string){
    	try {
    		JSONObject post_params = new JSONObject();
    		for(NameValuePair pair : pairs){
    			post_params.put(pair.getName(), pair.getValue());
    		}
			socket.emit(routing_string, post_params.toString());
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error(e.toString());
		}
	}*/
	
	public void get_message(String routing_string,Handler handler){
		get_message_task task = new get_message_task(routing_string, handler);
		task.execute();
	}
	
	public void send_message(List<NameValuePair> pairs, String routing_string){
		send_message_task task = new send_message_task(new ArrayList<NameValuePair>(pairs), routing_string);
		task.execute();
	}
	
	public SocketIO init_socket(final Intent routing_intent){

		String host = helper.get_base_url();
		logger.info(host);
		
		Properties headers = new Properties();
		
		logger.info("Cookie Store Size: " + helper.get_client().get_cookies().getCookies().size());
		
		for (Cookie cookie : helper.get_client().get_cookies().getCookies()){
			
			logger.info(cookie.getDomain());
			logger.info(cookie.getName());
			logger.info(cookie.getValue());
			
			if (helper.get_base_url().contains(cookie.getDomain())){
				logger.info("Cookie Properties Set");
				Date date = new Date();
			    date.setTime(date.getTime()+(100*24*60*60*1000));
				String expires = "; expires="+date+";";
				headers.setProperty("Cookie", cookie.getName()+"="+cookie.getValue()+expires+" path=/;domain="+cookie.getDomain());
			}
		}
		
		try {
			logger.info("Creating Socket");
			socket = new SocketIO(host,headers);
	        socket.connect(new IOCallback() {
	            @Override
	            public void onMessage(JSONObject json, IOAcknowledge ack) {
	                try {
	                    System.out.println("Server said:" + json.toString(2));
	                } catch (JSONException e) {
	                    e.printStackTrace();
	                }
	            }
	
	            @Override
	            public void onMessage(String data, IOAcknowledge ack) {
	                System.out.println("Server said: " + data);
	            }
	
	            @Override
	            public void onError(SocketIOException socketIOException) {
	                System.out.println("an Error occured");
	                socketIOException.printStackTrace();
	            }
	
	            @Override
	            public void onDisconnect() {
	                System.out.println("Connection terminated.");
	            }
	
	            @Override
	            public void onConnect() {
	                System.out.println("Connection established");
	            }
	
	            @Override
	            public void on(String event, IOAcknowledge ack, Object... args) {
	                System.out.println("Server triggered event '" + event + "'");
	                
	                if(event.equals("client_settings")){
	                	try {
							JSONObject result_object = new JSONObject(args[0].toString());
							logger.info("Received settings socket");
							logger.info(result_object.toString());
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
	                }
	                
	                if(event.equals("message")){
	                	try {
							JSONObject result_object = new JSONObject(args[0].toString());
							String message = result_object.getString("message");
							String user = result_object.getString("email");
							logger.info(message);
							logger.info(user);

							//chat_box.append("\n" + message + " - " + user);
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
	                }
	                
	                if(event.equals("parse_user")){
		                try {
		                	logger.info("Before");
			                JSONObject result_object = new JSONObject(args[0].toString());
							logger.info(result_object.toString());
			                List<NameValuePair> pairs = new ArrayList<NameValuePair>();
							pairs.add(new BasicNameValuePair("email", result_object.getString("email")));
							result_object = new JSONObject(helper.postResponsefromURL("login/", pairs));
							logger.info("After");
							logger.info(result_object.toString());
							if(result_object.getString("action").equals("success")){
								logger.info("Success!!!");
								context.startActivity(routing_intent);
							}else{
								logger.info("Error!!!");
							}
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
	                }
	            }
	        });
	        
			return socket;
	        
		} catch (MalformedURLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		return null;
	}
	
	//Make sure that the network is active and working...
	private class log_into_network_task extends AsyncTask<Void, Void, Void> {
		
		boolean intent_started;
		boolean returned_error;
		boolean test_login;
		TextView chat_box;
		ArrayList<NameValuePair> pairs;
		
		log_into_network_task(boolean test_login, ArrayList<NameValuePair> pairs){
			this.test_login = test_login;
			this.pairs = new ArrayList<NameValuePair>(pairs);
			this.chat_box = chat_box;
		}
		
		@Override
        protected void onPreExecute() {
			intent_started = returned_error = false;
			logger.info("Log into network init");
		}
		
		@Override
		protected Void doInBackground(Void... args) {
			synchronized (helper) {
				//Saves the new user. If the user isn't new, sends back an error with the user in the db
				logger.info("Sending post");
				
				//Set/Retrieve the cookie store
				helper.getResponsefromURL("android/call/");
				logger.info("Cookie Store Size: " + helper.get_client().get_cookies().getCookies().size());
				
				//Establish a connection with the server socket
				socket = init_socket(new Intent(context, next_activity));
				
				try {
					
					//Copy the client session cookie to the socket and try to login
					JSONObject emitting_object = new JSONObject();
					for(NameValuePair pair : pairs){
						emitting_object.put(pair.getName(), pair.getValue());
					}
			        socket.emit("login", emitting_object);
			        
			        //Establish a session with the server
			        
					//JSONObject result_object = new JSONObject(helper.postResponsefromURL("login/", pairs));
					//logger.info(result_object.toString());
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return null;
		}
		
		@Override
	    protected void onPostExecute(Void v) {
			
			/*logger.info("Intent Starting: " + String.valueOf(intent_started));
			logger.info("Passing Class: " + String.valueOf(pass_class));
			logger.info("Returned Error: " + String.valueOf(returned_error));
			logger.info("Test Login: " + String.valueOf(test_login));
			 if(!intent_started && pass_class && (!returned_error || test_login)){
				 logger.info("Starting New Activity...");
				 Intent myIntent = new Intent(context, next_activity);
				 intent_started = true;
				 context.startActivity(myIntent);
			 }else{
				 logger.warning("Login Authentication Failed!");
				 Toast.makeText(context, "Login Authentication Failed! Please Try Again", Toast.LENGTH_LONG).show();	
			 }*/
		}
	}
	
	//Make sure that the network is active and working...
	private class log_out_network_task extends AsyncTask<Void, Void, Void> {
		
		Handler handler = null;
		JSONObject result_array = null;
		boolean returned_error = false;
		
		@Override
        protected void onPreExecute() {
			logger.info("Network Logout Task Init");
		}
		
		@Override
		protected Void doInBackground(Void... container) {
			synchronized (helper) {
				try {
					logger.info("Requesting logout");
					result_array = new JSONObject(helper.getResponsefromURL("/logout"));
					logger.info("Logout returned array: " + result_array.toString());
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					logger.error("Error: " + e);
					returned_error = true;
					e.printStackTrace();
				}
			}
			logger.info("Logout Returning");
			return null;
		}
		
		@Override
	    protected void onPostExecute(Void arg0) {
			 //The data needs to be saved into the database here...
			if(handler != null){
				if(returned_error){
					logger.warning("There was an error with the request. Keep user logged in.");
					handler.sendEmptyMessage(5);
				}else{
					logger.info("Request valid. Logging user out");
					handler.sendEmptyMessage(4);
				}
			}else{
				logger.error("Return handler is null!");
			}
		}
	}

	private class get_message_task extends AsyncTask<Void, Void, Void> {
		
		String socket_router;
		Handler handler;
		String result;
		
		get_message_task(String socket_router, Handler handler){
			this.socket_router = socket_router;
			this.handler = handler;
		}
		
		@Override
        protected void onPreExecute() {
			logger.info("Sending Message...");
		}
		
		@Override
		protected Void doInBackground(Void... args) {
			synchronized (helper) {
				result = helper.getResponsefromURL(this.socket_router);
			}
			return null;
		}
		
		@Override
	    protected void onPostExecute(Void v) {
			Message msg = new Message();
			msg.obj = result;
			msg.what = 0;
			handler.dispatchMessage(msg);
		}
	}
	
	//Make sure that the network is active and working...
	private class send_message_task extends AsyncTask<Void, Void, Void> {
		
		String socket_router;
		ArrayList<NameValuePair> pairs;
		
		send_message_task(ArrayList<NameValuePair> pairs, String socket_router){
			this.pairs = new ArrayList<NameValuePair>(pairs);
			this.socket_router = socket_router;
		}
		
		@Override
        protected void onPreExecute() {
			logger.info("Sending Message...");
		}
		
		@Override
		protected Void doInBackground(Void... args) {
			synchronized (helper) {
				//message_text
				try {
					JSONObject result_object = new JSONObject(helper.postResponsefromURL(this.socket_router, pairs));
					logger.info(result_object.toString());
				} catch (JSONException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			return null;
		}
		
		@Override
	    protected void onPostExecute(Void v) {

		}
	}
}
